home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CU Amiga Super CD-ROM 11
/
CU Amiga Magazine's Super CD-ROM 11 (1997)(EMAP Images)(GB)(Track 1 of 3)[!][issue 1997-06].iso
/
cucd
/
programming
/
oberonv4
/
source
/
system
/
input.mod
(
.txt
)
< prev
next >
Wrap
Oberon Text
|
1997-01-28
|
6KB
|
171 lines
Syntax10.Scn.Fnt
Syntax10b.Scn.Fnt
ParcElems
Alloc
MODULE Input; (* OJ 5-Nov-96, RED parts are still not very nice *)
IMPORT SYSTEM, E := AmigaExec, IE := AmigaInputEvent, I := AmigaIntuition, T := AmigaTimer, Amiga, HostSys;
CONST
N = 32; (* buffersize for keystrokes *)
TimeUnit*= 1000; (* resolution of Time() is one millisecond *)
MR = 0; MM = 1; ML = 2;
ESC = 1BX; SETUP = 0A4X; FF = 0CX; QUIT = 0EFX;
CUP=0C1X; CDOWN=0C2X; CLEFT=0C4X; CRIGHT=0C3X;
BREAK1=0ACX; BREAK2=0ADX;
DEL = 07FX; BS=08X;
WindowPtr = POINTER TO I.Window;
TaskPointer = POINTER TO E.Task;
n, in, out :INTEGER; buf : ARRAY N OF CHAR;
mkeys : SET;
time, ticksPerUnit, clklo0 : LONGINT; clk : T.EClockVal;
R2O : ARRAY 256 OF CHAR;
mainTask, inputTask : E.TaskPtr;
exceptSig : SET;
PROCEDURE Exception();
(* exception handler for CTRL-SHIFT-Del *)
VAR d0 : SET;
BEGIN
SYSTEM.GETREG( 0, d0 );
d0 := E.SetExcept( exceptSig, exceptSig );
HALT(24);
SYSTEM.PUTREG( 0, d0 )
END Exception;
PROCEDURE InputTask();
(* handles messages from window port *)
TYPE IntuiMessagePtr=POINTER TO I.IntuiMessage;
CONST deadKeys = { IE.lShift, IE.rShift, IE.capsLock, IE.control, IE.lAlt, IE.rAlt, IE.lCommand, IE.rCommand };
VAR window : WindowPtr; msg : IntuiMessagePtr; class, qual : SET; code : INTEGER; ch : CHAR;
PROCEDURE Put(ch: CHAR);
BEGIN
IF n<N THEN buf[in] := ch; in := (in + 1) MOD N; INC(n) END;
END Put;
BEGIN
window := SYSTEM.VAL(WindowPtr, Amiga.window);
I.ModifyIDCMP( Amiga.window, {I.rawKey,I.vanillaKey,I.mouseButtons,I.closeWindow} );
LOOP
E.WaitPort(window.userPort);
msg := SYSTEM.VAL(IntuiMessagePtr, E.GetMsg(window.userPort));
WHILE msg # NIL DO
class := msg.class; code := msg.code; qual := SYSTEM.VAL( SET, LONG(msg.qualifier) );
E.ReplyMsg(SYSTEM.VAL(E.MessagePtr, msg));
IF I.mouseButtons IN class THEN
CASE code OF
| I.selectDown:
IF (window.mouseY=0) & (window.mouseX=Amiga.Width-1) & (~Amiga.WBWindow) THEN
I.ScreenToBack( window.wScreen )
ELSE
INCL(mkeys, ML)
END
| I.selectUp: EXCL(mkeys, ML)
| I.menuDown: INCL(mkeys, MR)
| I.menuUp: EXCL(mkeys, MR)
| I.middleDown: INCL(mkeys, MM)
| I.middleUp: EXCL(mkeys, MM)
END;
ELSIF I.rawKey IN class THEN
ch := R2O[code];
IF qual * {IE.lShift, IE.rShift, IE.capsLock} # {} THEN
IF ch = BREAK1 THEN ch := BREAK2 END;
END;
IF ch # 0X THEN Put( ch ) END;
ELSIF I.vanillaKey IN class THEN
ch := CHR(code); qual := qual*deadKeys;
IF qual = {IE.rCommand} THEN
CASE ch OF
| "x": Put( CHR(0FCH) ) (* Cut *)
| "c": Put( CHR(0FDH) ) (* Copy *)
| "v": Put( CHR(0FEH) ) (* Paste *)
ELSE
(* do nothing *)
END;
ELSIF (qual = {IE.control,IE.lShift}) & (ch = DEL) THEN
E.Signal( mainTask, exceptSig );
ELSE
IF ch=BS THEN ch:=DEL ELSIF ch=DEL THEN ch:=BS END;
Put( HostSys.toOberon( ch ));
END;
ELSIF I.closeWindow IN class THEN Put( QUIT );
END;
msg := SYSTEM.VAL(IntuiMessagePtr, E.GetMsg(window.userPort))
END;
END;
END InputTask;
PROCEDURE Available*(): INTEGER;
BEGIN
RETURN n
END Available;
PROCEDURE Read*(VAR ch: CHAR);
BEGIN
IF n=0 THEN HALT(99) END;
DEC(n); ch := buf[out]; out := (out + 1) MOD N
END Read;
PROCEDURE Mouse*(VAR keys: SET; VAR x, y: INTEGER);
VAR window : WindowPtr; sp : SHORTINT;
BEGIN
window := SYSTEM.VAL(WindowPtr, Amiga.window);
IF I.windowActive IN window.flags THEN
keys := mkeys;
IF Amiga.useLAltAsMouse THEN
SYSTEM.GET(0BFEC01H,sp);
IF sp = 55 THEN INCL( keys, MM ) (* ELSE EXCL( keys, MM ) *) END;
END;
x := window.mouseX; y := Amiga.Height-window.mouseY-1;
IF x<0 THEN x:=0 ELSIF x>=Amiga.Width THEN x:=Amiga.Width-1 END;
IF y<0 THEN y:=0 ELSIF y>=Amiga.Height THEN y:=Amiga.Height-1 END;
ELSE
keys := {}; x := 0; y := 0;
END;
END Mouse;
PROCEDURE SetMouseLimits*(w, h: INTEGER);
(* NOT SUPPORTED *)
END SetMouseLimits;
PROCEDURE Time*(): LONGINT;
(* should be called at least every 40 mins! *)
VAR d : LONGINT;
BEGIN
d := T.ReadEClock( SYSTEM.ADR(clk) );
d := ABS(clk.lo - clklo0);
clklo0 := clk.lo - (d MOD ticksPerUnit);
INC( time, d DIV ticksPerUnit);
RETURN time
END Time;
PROCEDURE InitRAWtoOberon; (* Map RAW-Key to Oberon Char *)
VAR i: INTEGER;
BEGIN
FOR i:=0 TO 255 DO R2O[i]:=CHR(0) END;
R2O[50H]:=SETUP; (* F1 *)
R2O[51H]:=ESC; (* F2 *)
R2O[52H]:=BREAK1; (* F3 *)
R2O[53H]:=FF; (* F4 *)
R2O[54H]:=0F5X; (* F5 *)
R2O[55H]:=0F6X; (* F6 *)
R2O[56H]:=0F7X; (* F7 *)
R2O[57H]:=0F8X; (* F8 *)
R2O[58H]:=0F9X; (* F9 *)
R2O[59H]:=0FAX; (* F10 *)
R2O[5FH]:=0FBX; (* HELP *)
R2O[4CH]:=CUP; (* Cursor UP *)
R2O[4DH]:=CDOWN; (* Cursor DOWN *)
R2O[4EH]:=CRIGHT; (* Cursor RIGHT *)
R2O[4FH]:=CLEFT; (* Cursor LEFT *)
END InitRAWtoOberon;
PROCEDURE Init();
VAR task : TaskPointer; proc : PROCEDURE;
BEGIN
n := 0; in := 0; out := 0;
ticksPerUnit := (T.ReadEClock( SYSTEM.ADR(clk) ) + (TimeUnit DIV 2)) DIV TimeUnit;
clklo0 := clk.lo; time := 0;
InitRAWtoOberon;
mainTask := E.FindTask( E.null ); exceptSig := E.SetExcept( {}, {} );
inputTask := E.CreateTask("O4A-InputTask",1,InputTask,4096);
task := SYSTEM.VAL( TaskPointer, mainTask ); proc := Exception;
task.exceptCode := SYSTEM.VAL( LONGINT, proc );
END Init;
PROCEDURE Term();
BEGIN
IF inputTask#E.null THEN E.RemTask(inputTask) END;
END Term;
BEGIN
inputTask:=E.null; Amiga.TermProcedure(Term);
Init();
END Input.